home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1993 July / InfoMagic USENET CD-ROM July 1993.ISO / sources / misc / volume23 / pascal / part01 next >
Encoding:
Text File  |  1991-09-27  |  55.6 KB  |  1,873 lines

  1. Newsgroups: comp.sources.misc
  2. From: steven@cwi.nl (Steven Pemberton)
  3. Subject:  v23i025:  pascal - Public domain Pascal Compiler and Interpreter, Part01/03
  4. Message-ID: <csm-v23i025=pascal.231008@sparky.IMD.Sterling.COM>
  5. X-Md4-Signature: ffb57898f8934e31e7b62c5bee2a26d1
  6. Date: Fri, 27 Sep 1991 04:11:51 GMT
  7. Approved: kent@sparky.imd.sterling.com
  8.  
  9. Submitted-by: steven@cwi.nl (Steven Pemberton)
  10. Posting-number: Volume 23, Issue 25
  11. Archive-name: pascal/part01
  12. Environment: Pascal
  13.  
  14. Due to public demand following postings to comp.lang.misc and
  15. comp.compilers, here are the sources of a public domain Pascal
  16. compiler and interpreter.
  17.  
  18. This is the Pascal source of a public domain Pascal compiler and
  19. interpreter. The entire code is documented in the book:
  20.     Pascal Implementation
  21.     by Steven Pemberton and Martin Daniels
  22.     published by Ellis Horwood, Chichester, UK,
  23. (also available in Japanese).
  24. It was distributed by John Wiley in other countries, but now that
  25. Prentice Hall has taken over Ellis Horwood, that may have changed.
  26.  
  27. Best wishes,
  28.  
  29. Steven Pemberton, CWI, Amsterdam; steven@cwi.nl
  30. -----
  31. #!/bin/sh
  32. # This is a shell archive (produced by shar 3.49)
  33. # To extract the files from this archive, save it to a file, remove
  34. # everything above the "!/bin/sh" line above, and type "sh file_name".
  35. #
  36. # existing files will NOT be overwritten unless -c is specified
  37. #
  38. # This is part 1 of a multipart archive                                    
  39. # do not concatenate these parts, unpack them in order with /bin/sh        
  40. #
  41. # This shar contains:
  42. # length  mode       name
  43. # ------ ---------- ------------------------------------------
  44. #   6433 -rw-r--r-- READ.ME
  45. # 117626 -rw-r--r-- pcom.p
  46. #  28139 -rw-r--r-- pint.p
  47. #
  48. if test -r _shar_seq_.tmp; then
  49.     echo 'Must unpack archives in sequence!'
  50.     echo Please unpack part `cat _shar_seq_.tmp` next
  51.     exit 1
  52. fi
  53. # ============= READ.ME ==============
  54. if test -f 'READ.ME' -a X"$1" != X"-c"; then
  55.     echo 'x - skipping READ.ME (File already exists)'
  56.     rm -f _shar_wnt_.tmp
  57. else
  58. > _shar_wnt_.tmp
  59. echo 'x - extracting READ.ME (Text)'
  60. sed 's/^X//' << 'SHAR_EOF' > 'READ.ME' &&
  61. This is the Pascal source of a public domain Pascal compiler and
  62. interpreter. The entire code is documented in the book:
  63. X    Pascal Implementation
  64. X    by Steven Pemberton and Martin Daniels
  65. X    published by Ellis Horwood, Chichester, UK,
  66. (also available in Japanese).
  67. It was distributed by John Wiley in other countries, but now that
  68. Prentice Hall has taken over Ellis Horwood, that may have changed.
  69. X
  70. Steven Pemberton is contactable by email as steven@cwi.nl.
  71. X
  72. The code here is slightly different from that in the book, but the
  73. line numbers have been kept the same.  The changes were to allow
  74. modern Pascal compilers to compile the source (there were some slight
  75. laxities in the original code).
  76. X
  77. The type marktype is added for the parameters of the routines mark and
  78. release:
  79. X    76c76
  80. X    < 
  81. X    ---
  82. X    >      marktype= ^integer;
  83. X
  84. The type setty (which represents set types) is added for the new type
  85. compatibility rules of ISO Pascal:
  86. X    95c95
  87. X    < 
  88. X    ---
  89. X    >      setty = set of setlow..sethigh;
  90. X    100c100
  91. X    <                          pset: (pval: set of setlow..sethigh);
  92. X    ---
  93. X    >                          pset: (pval: setty);
  94. X
  95. Missing variant parts:
  96. X    123c123
  97. X    <                                   declared: (fconst: ctp));
  98. X    ---
  99. X    >                                   declared: (fconst: ctp); standard: ());
  100. X    145a146
  101. X    >                      types: ();
  102. X    149,150c150
  103. X    <                      proc,
  104. X    <                      func:  (case pfdeckind: declkind of
  105. X    ---
  106. X    >                      proc, func:  (case pfdeckind: declkind of
  107. X    154,155c154,155
  108. X    <                                            actual: (forwdecl, extern:
  109. X    <                                                     boolean)))
  110. X    ---
  111. X    >                                            actual: (forwdecl, extern: boolean);
  112. X    >                                            formal: ()))
  113. X
  114. Pcom has the files prr and prd as standard identifiers. You have to
  115. declare them for other compilers:
  116. X    193d192
  117. X    < 
  118. X    194a194
  119. X    >     prr: text; (* comment this out when compiling with pcom *)
  120. X    299d298
  121. X    < 
  122. X
  123. Other compilers don't have the routines mark and release. Their
  124. effective semantics are null; you just waste heap:
  125. X    300a300,301
  126. X    >   procedure mark(var p: marktype); begin end;
  127. X    >   procedure release(p: marktype); begin end;
  128. X    302d302
  129. X    < 
  130. X
  131. Output the line number with error messages, so that if the listing
  132. option has been switched off, you still know which line is in error:
  133. X    307c307
  134. X    <       begin write(output,' ****  ':15);
  135. X    ---
  136. X    >       begin write(output,linecount:6,' ****  ':9);
  137. X
  138. Accept tabs as white-space as well:
  139. X    398c398
  140. X    <     repeat while (ch = ' ') and not eol do nextch;
  141. X    ---
  142. X    >     repeat while ((ch = ' ') or (ch = '    ')) and not eol do nextch;
  143. X
  144. Jumping from the then part of an if into the else part is not allowed;
  145. fix cases like 1..10 in another way:
  146. X    429c429
  147. X    <           if (ch = '.') or (ch = 'e') then
  148. X    ---
  149. X    >           if ((ch = '.') and (input^ <> '.')) or (ch = 'e') then
  150. X    434c434
  151. X    <                       nextch; if ch = '.' then begin ch := ':'; goto 3 end;
  152. X    ---
  153. X    >                       nextch; (*if ch = '.' then begin ch := ':'; goto 3 end;*)
  154. X
  155. Fix modern type mismatches:
  156. X    668c668
  157. X    <   procedure align(fsp: stp; var flc: integer);
  158. X    ---
  159. X    >   procedure align(fsp: stp; var flc: addrrange);
  160. X
  161. An identifier misspelled after the 8th character:
  162. X    872c872
  163. X    <           if sy = stringconstsy then
  164. X    ---
  165. X    >           if sy = stringconst then
  166. X
  167. Unused variables, and new type names:
  168. X    1529,1531c1529,1531
  169. X    <       var oldlev: 0..maxlevel; lsy: symbol; lcp,lcp1: ctp; lsp: stp;
  170. X    <           forw: boolean; oldtop: disprange; parcnt: integer;
  171. X    <           llc,lcm: addrrange; lbname: integer; markp: ^integer;
  172. X    ---
  173. X    >       var oldlev: 0..maxlevel; lcp,lcp1: ctp; lsp: stp;
  174. X    >           forw: boolean; oldtop: disprange;
  175. X    >           llc,lcm: addrrange; lbname: integer; markp: marktype;
  176. X    1535c1535
  177. X    <           llc: addrrange; count,lsize: integer;
  178. X    ---
  179. X    >           llc,lsize: addrrange; count: integer;
  180. X    1819c1819
  181. X    <           i, entname, segsize: integer;
  182. X    ---
  183. X    >           entname, segsize: integer;
  184. X    2087c2087
  185. X    <         var lattr: attr; lcp: ctp; lsize,lmin,lmax: integer;
  186. X    ---
  187. X    >         var lattr: attr; lcp: ctp; lsize: addrrange; lmin,lmax: integer;
  188. X    2248c2248
  189. X    <             var lcp:ctp; llev:levrange; laddr:addrrange;
  190. X    ---
  191. X    >             var llev:levrange; laddr:addrrange;
  192. X    2306c2306
  193. X    <                 lcp:ctp; llev:levrange; laddr,len:addrrange;
  194. X    ---
  195. X    >                 llev:levrange; laddr,len:addrrange;
  196. X    2456,2457c2456,2457
  197. X    <             var lsp,lsp1: stp; varts,lmin,lmax: integer;
  198. X    <                 lsize,lsz: addrrange; lval: valu;
  199. X    ---
  200. X    >             var lsp,lsp1: stp; varts: integer;
  201. X    >                 lsize: addrrange; lval: valu;
  202. X    2750c2750
  203. X    <                     cstpart: set of 0..47; lsp: stp;
  204. X    ---
  205. X    >                     cstpart: setty; lsp: stp;
  206. X
  207. Unix pc can't cope with this line:
  208. X    2926c2926
  209. X    <             (*/*)     rdiv: begin
  210. X    ---
  211. X    >             (* / *)   rdiv: begin
  212. X
  213. More unused variables:
  214. X    3318c3318
  215. X    <           var lattr: attr; lsp: stp;  lsy: symbol;
  216. X    ---
  217. X    >           var lattr: attr;  lsy: symbol;
  218. X    3642c3642
  219. X    <     var sp: stp;
  220. X    ---
  221. X    > 
  222. X
  223. Produce code as default:
  224. X    3800c3800
  225. X    <     prtables := false; list := true; prcode := false; debug := true;
  226. X    ---
  227. X    >     prtables := false; list := true; prcode := true; debug := true;
  228. X
  229. Unused variable:
  230. X    3868c3868
  231. X    <       var i: integer; ch: char;
  232. X    ---
  233. X    >       var i: integer;
  234. X
  235. Other compilers need to rewrite prr before using it:
  236. X    3995,3996c3995,3996
  237. X    <   (*compile:*)
  238. X    <   (**********)
  239. X    ---
  240. X    >   (*compile:*) rewrite(prr); (*comment this out when compiling with pcom *)
  241. X    >   (**********)
  242. X
  243. Differences in the interpreter are minimal: a set type has been added:
  244. X
  245. X    45a46
  246. X    >       settype     = set of 0..58;
  247. X    63c64
  248. X    <                                 sett       :(vs :set of 0..47);
  249. X    ---
  250. X    >                                 sett       :(vs :settype);
  251. X    225c226
  252. X    <       var name :alfa;  b :boolean;  r :real;  s :set of 0..58;
  253. X    ---
  254. X    >       var name :alfa;  b :boolean;  r :real;  s :settype;
  255. X
  256. End of differences
  257. SHAR_EOF
  258. chmod 0644 READ.ME ||
  259. echo 'restore of READ.ME failed'
  260. Wc_c="`wc -c < 'READ.ME'`"
  261. test 6433 -eq "$Wc_c" ||
  262.     echo 'READ.ME: original size 6433, current size' "$Wc_c"
  263. rm -f _shar_wnt_.tmp
  264. fi
  265. # ============= pcom.p ==============
  266. if test -f 'pcom.p' -a X"$1" != X"-c"; then
  267.     echo 'x - skipping pcom.p (File already exists)'
  268.     rm -f _shar_wnt_.tmp
  269. else
  270. > _shar_wnt_.tmp
  271. echo 'x - extracting pcom.p (Text)'
  272. sed 's/^X//' << 'SHAR_EOF' > 'pcom.p' &&
  273. (*$c+,t-,d-,l-*)
  274. X (***********************************************
  275. X  *                        *
  276. X  *     Portable Pascal compiler        *
  277. X  *     ************************        *
  278. X  *                        *
  279. X  *        Pascal P4            *
  280. X  *                        *
  281. X  *     Authors:                *
  282. X  *          Urs Ammann            *
  283. X  *          Kesav Nori            *
  284. X  *          Christian Jacobi            *
  285. X  *     Address:                *
  286. X  *      Institut Fuer Informatik        *
  287. X  *      Eidg. Technische Hochschule        *
  288. X  *      CH-8096 Zuerich            *
  289. X  *                        *
  290. X  *  This code is fully documented in the book    *
  291. X  *       "Pascal Implementation"        *
  292. X  *   by Steven Pemberton and Martin Daniels    *
  293. X  * published by Ellis Horwood, Chichester, UK    *
  294. X  *       (also available in Japanese)        *
  295. X  *                        *
  296. X  * Steven Pemberton, CWI/AA,            *
  297. X  * Kruislaan 413, 1098 SJ Amsterdam, NL    *
  298. X  * steven@cwi.nl                *
  299. X  *                        *
  300. X  *                        *
  301. X  ***********************************************)
  302. X
  303. program pascalcompiler(input,output,prr);
  304. X
  305. const displimit = 20; maxlevel = 10;
  306. X   intsize     =      1;
  307. X   intal       =      1;
  308. X   realsize    =      1;
  309. X   realal      =      1;
  310. X   charsize    =      1;
  311. X   charal      =      1;
  312. X   charmax     =      1;
  313. X   boolsize    =      1;
  314. X   boolal      =      1;
  315. X   ptrsize     =      1;
  316. X   adral       =      1;
  317. X   setsize     =      1;
  318. X   setal       =      1;
  319. X   stackal     =      1;
  320. X   stackelsize =      1;
  321. X   strglgth    =     16;
  322. X   sethigh     =     47;
  323. X   setlow      =      0;
  324. X   ordmaxchar  =     63;
  325. X   ordminchar  =      0;
  326. X   maxint      =  32767;
  327. X   lcaftermarkstack = 5;
  328. X   fileal      = charal;
  329. X   (* stackelsize = minimum size for 1 stackelement
  330. X          = k*stackal
  331. X      stackal     = scm(all other al-constants)
  332. X      charmax     = scm(charsize,charal)
  333. X            scm = smallest common multiple
  334. X      lcaftermarkstack >= 4*ptrsize+max(x-size)
  335. X            = k1*stackelsize      *)
  336. X   maxstack   =       1;
  337. X   parmal     = stackal;
  338. X   parmsize   = stackelsize;
  339. X   recal      = stackal;
  340. X   filebuffer =       4;
  341. X   maxaddr    =  maxint;
  342. X
  343. X
  344. X
  345. type                            (*describing:*)
  346. X                                (*************)
  347. X
  348. X     marktype= ^integer;
  349. X                                (*basic symbols*)
  350. X                                (***************)
  351. X
  352. X     symbol = (ident,intconst,realconst,stringconst,notsy,mulop,addop,relop,
  353. X           lparent,rparent,lbrack,rbrack,comma,semicolon,period,arrow,
  354. X           colon,becomes,labelsy,constsy,typesy,varsy,funcsy,progsy,
  355. X           procsy,setsy,packedsy,arraysy,recordsy,filesy,forwardsy,
  356. X           beginsy,ifsy,casesy,repeatsy,whilesy,forsy,withsy,
  357. X           gotosy,endsy,elsesy,untilsy,ofsy,dosy,tosy,downtosy,
  358. X           thensy,othersy);
  359. X     operator = (mul,rdiv,andop,idiv,imod,plus,minus,orop,ltop,leop,geop,gtop,
  360. X         neop,eqop,inop,noop);
  361. X     setofsys = set of symbol;
  362. X     chtp = (letter,number,special,illegal,
  363. X         chstrquo,chcolon,chperiod,chlt,chgt,chlparen,chspace);
  364. X
  365. X                                (*constants*)
  366. X                                (***********)
  367. X     setty = set of setlow..sethigh;
  368. X     cstclass = (reel,pset,strg);
  369. X     csp = ^ constant;
  370. X     constant = record case cclass: cstclass of
  371. X             reel: (rval: packed array [1..strglgth] of char);
  372. X             pset: (pval: setty);
  373. X             strg: (slgth: 0..strglgth;
  374. X                sval: packed array [1..strglgth] of char)
  375. X               end;
  376. X
  377. X     valu = record case intval: boolean of  (*intval never set nor tested*)
  378. X             true:  (ival: integer);
  379. X             false: (valp: csp)
  380. X           end;
  381. X
  382. X                               (*data structures*)
  383. X                               (*****************)
  384. X     levrange = 0..maxlevel; addrrange = 0..maxaddr;
  385. X     structform = (scalar,subrange,pointer,power,arrays,records,files,
  386. X           tagfld,variant);
  387. X     declkind = (standard,declared);
  388. X     stp = ^ structure; ctp = ^ identifier;
  389. X
  390. X     structure = packed record
  391. X           marked: boolean;   (*for test phase only*)
  392. X           size: addrrange;
  393. X           case form: structform of
  394. X             scalar:   (case scalkind: declkind of
  395. X                  declared: (fconst: ctp); standard: ());
  396. X             subrange: (rangetype: stp; min,max: valu);
  397. X             pointer:  (eltype: stp);
  398. X             power:    (elset: stp);
  399. X             arrays:   (aeltype,inxtype: stp);
  400. X             records:  (fstfld: ctp; recvar: stp);
  401. X             files:    (filtype: stp);
  402. X             tagfld:   (tagfieldp: ctp; fstvar: stp);
  403. X             variant:  (nxtvar,subvar: stp; varval: valu)
  404. X           end;
  405. X
  406. X                                (*names*)
  407. X                                (*******)
  408. X
  409. X     idclass = (types,konst,vars,field,proc,func);
  410. X     setofids = set of idclass;
  411. X     idkind = (actual,formal);
  412. X     alpha = packed array [1..8] of char;
  413. X
  414. X     identifier = packed record
  415. X           name: alpha; llink, rlink: ctp;
  416. X           idtype: stp; next: ctp;
  417. X           case klass: idclass of
  418. X             types: ();
  419. X             konst: (values: valu);
  420. X             vars:  (vkind: idkind; vlev: levrange; vaddr: addrrange);
  421. X             field: (fldaddr: addrrange);
  422. X             proc, func:  (case pfdeckind: declkind of
  423. X                  standard: (key: 1..15);
  424. X                  declared: (pflev: levrange; pfname: integer;
  425. X                      case pfkind: idkind of
  426. X                       actual: (forwdecl, extern: boolean);
  427. X                       formal: ()))
  428. X           end;
  429. X
  430. X
  431. X     disprange = 0..displimit;
  432. X     where = (blck,crec,vrec,rec);
  433. X
  434. X                                (*expressions*)
  435. X                                (*************)
  436. X     attrkind = (cst,varbl,expr);
  437. X     vaccess = (drct,indrct,inxd);
  438. X
  439. X     attr = record typtr: stp;
  440. X          case kind: attrkind of
  441. X        cst:   (cval: valu);
  442. X        varbl: (case access: vaccess of
  443. X              drct: (vlevel: levrange; dplmt: addrrange);
  444. X              indrct: (idplmt: addrrange))
  445. X          end;
  446. X
  447. X     testp = ^ testpointer;
  448. X     testpointer = packed record
  449. X             elt1,elt2 : stp;
  450. X             lasttestp : testp
  451. X           end;
  452. X
  453. X                                 (*labels*)
  454. X                                 (********)
  455. X     lbp = ^ labl;
  456. X     labl = record nextlab: lbp; defined: boolean;
  457. X           labval, labname: integer
  458. X        end;
  459. X
  460. X     extfilep = ^filerec;
  461. X     filerec = record filename:alpha; nextfile:extfilep end;
  462. X
  463. (*-------------------------------------------------------------------------*)
  464. X
  465. var
  466. (*    prr: text; (* comment this out when compiling with pcom *)
  467. X                    (*returned by source program scanner
  468. X                     insymbol:
  469. X                     **********)
  470. X
  471. X    sy: symbol;             (*last symbol*)
  472. X    op: operator;           (*classification of last symbol*)
  473. X    val: valu;              (*value of last constant*)
  474. X    lgth: integer;          (*length of last string constant*)
  475. X    id: alpha;              (*last identifier (possibly truncated)*)
  476. X    kk: 1..8;               (*nr of chars in last identifier*)
  477. X    ch: char;               (*last character*)
  478. X    eol: boolean;           (*end of line flag*)
  479. X
  480. X
  481. X                    (*counters:*)
  482. X                    (***********)
  483. X
  484. X    chcnt: integer;         (*character counter*)
  485. X    lc,ic: addrrange;           (*data location and instruction counter*)
  486. X    linecount: integer;
  487. X
  488. X
  489. X                    (*switches:*)
  490. X                    (***********)
  491. X
  492. X    dp,                 (*declaration part*)
  493. X    prterr,             (*to allow forward references in pointer type
  494. X                      declaration by suppressing error message*)
  495. X    list,prcode,prtables: boolean;  (*output options for
  496. X                    -- source program listing
  497. X                    -- printing symbolic code
  498. X                    -- displaying ident and struct tables
  499. X                    --> procedure option*)
  500. X    debug: boolean;
  501. X
  502. X
  503. X                    (*pointers:*)
  504. X                    (***********)
  505. X    parmptr,
  506. X    intptr,realptr,charptr,
  507. X    boolptr,nilptr,textptr: stp;    (*pointers to entries of standard ids*)
  508. X    utypptr,ucstptr,uvarptr,
  509. X    ufldptr,uprcptr,ufctptr,    (*pointers to entries for undeclared ids*)
  510. X    fwptr: ctp;             (*head of chain of forw decl type ids*)
  511. X    fextfilep: extfilep;        (*head of chain of external files*)
  512. X    globtestp: testp;           (*last testpointer*)
  513. X
  514. X
  515. X                    (*bookkeeping of declaration levels:*)
  516. X                    (************************************)
  517. X
  518. X    level: levrange;        (*current static level*)
  519. X    disx,               (*level of last id searched by searchid*)
  520. X    top: disprange;         (*top of display*)
  521. X
  522. X    display:            (*where:   means:*)
  523. X      array [disprange] of
  524. X    packed record           (*=blck:   id is variable id*)
  525. X      fname: ctp; flabel: lbp;  (*=crec:   id is field id in record with*)
  526. X      case occur: where of      (*     constant address*)
  527. X        crec: (clev: levrange;  (*=vrec:   id is field id in record with*)
  528. X          cdspl: addrrange);(*     variable address*)
  529. X        vrec: (vdspl: addrrange)
  530. X      end;              (* --> procedure withstatement*)
  531. X
  532. X
  533. X                    (*error messages:*)
  534. X                    (*****************)
  535. X
  536. X    errinx: 0..10;          (*nr of errors in current source line*)
  537. X    errlist:
  538. X      array [1..10] of
  539. X    packed record pos: integer;
  540. X              nmr: 1..400
  541. X           end;
  542. X
  543. X
  544. X
  545. X                    (*expression compilation:*)
  546. X                    (*************************)
  547. X
  548. X    gattr: attr;            (*describes the expr currently compiled*)
  549. X
  550. X
  551. X                    (*structured constants:*)
  552. X                    (***********************)
  553. X
  554. X    constbegsys,simptypebegsys,typebegsys,blockbegsys,selectsys,facbegsys,
  555. X    statbegsys,typedels: setofsys;
  556. X    chartp : array[char] of chtp;
  557. X    rw:  array [1..35(*nr. of res. words*)] of alpha;
  558. X    frw: array [1..9] of 1..36(*nr. of res. words + 1*);
  559. X    rsy: array [1..35(*nr. of res. words*)] of symbol;
  560. X    ssy: array [char] of symbol;
  561. X    rop: array [1..35(*nr. of res. words*)] of operator;
  562. X    sop: array [char] of operator;
  563. X    na:  array [1..35] of alpha;
  564. X    mn:  array [0..60] of packed array [1..4] of char;
  565. X    sna: array [1..23] of packed array [1..4] of char;
  566. X    cdx: array [0..60] of -4..+4;
  567. X    pdx: array [1..23] of -7..+7;
  568. X    ordint: array [char] of integer;
  569. X
  570. X    intlabel,mxint10,digmax: integer;
  571. (*-------------------------------------------------------------------------*)
  572. X  procedure mark(var p: marktype); begin end;
  573. X  procedure release(p: marktype); begin end;
  574. X
  575. X  procedure endofline;
  576. X    var lastpos,freepos,currpos,currnmr,f,k: integer;
  577. X  begin
  578. X    if errinx > 0 then   (*output error messages*)
  579. X      begin write(output,linecount:6,' ****  ':9);
  580. X    lastpos := 0; freepos := 1;
  581. X    for k := 1 to errinx do
  582. X      begin
  583. X        with errlist[k] do
  584. X          begin currpos := pos; currnmr := nmr end;
  585. X        if currpos = lastpos then write(output,',')
  586. X        else
  587. X          begin
  588. X        while freepos < currpos do
  589. X          begin write(output,' '); freepos := freepos + 1 end;
  590. X        write(output,'^');
  591. X        lastpos := currpos
  592. X          end;
  593. X        if currnmr < 10 then f := 1
  594. X        else if currnmr < 100 then f := 2
  595. X          else f := 3;
  596. X        write(output,currnmr:f);
  597. X        freepos := freepos + f + 1
  598. X      end;
  599. X    writeln(output); errinx := 0
  600. X      end;
  601. X    linecount := linecount + 1;
  602. X    if list and (not eof(input)) then
  603. X      begin write(output,linecount:6,'  ':2);
  604. X    if dp then write(output,lc:7) else write(output,ic:7);
  605. X    write(output,' ')
  606. X      end;
  607. X    chcnt := 0
  608. X  end  (*endofline*) ;
  609. X
  610. X  procedure error(ferrnr: integer);
  611. X  begin
  612. X    if errinx >= 9 then
  613. X      begin errlist[10].nmr := 255; errinx := 10 end
  614. X    else
  615. X      begin errinx := errinx + 1;
  616. X    errlist[errinx].nmr := ferrnr
  617. X      end;
  618. X    errlist[errinx].pos := chcnt
  619. X  end (*error*) ;
  620. X
  621. X  procedure insymbol;
  622. X    (*read next basic symbol of source program and return its
  623. X    description in the global variables sy, op, id, val and lgth*)
  624. X    label 1,2,3;
  625. X    var i,k: integer;
  626. X    digit: packed array [1..strglgth] of char;
  627. X    string: packed array [1..strglgth] of char;
  628. X    lvp: csp; test: boolean;
  629. X
  630. X    procedure nextch;
  631. X    begin if eol then
  632. X      begin if list then writeln(output); endofline
  633. X      end;
  634. X      if not eof(input) then
  635. X       begin eol := eoln(input); read(input,ch);
  636. X    if list then write(output,ch);
  637. X    chcnt := chcnt + 1
  638. X       end
  639. X      else
  640. X    begin writeln(output,'   *** eof ','encountered');
  641. X      test := false
  642. X    end
  643. X    end;
  644. X
  645. X    procedure options;
  646. X    begin
  647. X      repeat nextch;
  648. X    if ch <> '*' then
  649. X      begin
  650. X        if ch = 't' then
  651. X          begin nextch; prtables := ch = '+' end
  652. X        else
  653. X          if ch = 'l' then
  654. X        begin nextch; list := ch = '+';
  655. X          if not list then writeln(output)
  656. X        end
  657. X          else
  658. X         if ch = 'd' then
  659. X           begin nextch; debug := ch = '+' end
  660. X         else
  661. X        if ch = 'c' then
  662. X          begin nextch; prcode := ch = '+' end;
  663. X        nextch
  664. X      end
  665. X      until ch <> ','
  666. X    end (*options*) ;
  667. X
  668. X  begin (*insymbol*)
  669. X  1:
  670. X    repeat while ((ch = ' ') or (ch = '    ')) and not eol do nextch;
  671. X      test := eol;
  672. X      if test then nextch
  673. X    until not test;
  674. X    if chartp[ch] = illegal then
  675. X      begin sy := othersy; op := noop;
  676. X    error(399); nextch
  677. X      end
  678. X    else
  679. X    case chartp[ch] of
  680. X      letter:
  681. X    begin k := 0;
  682. X      repeat
  683. X        if k < 8 then
  684. X         begin k := k + 1; id[k] := ch end ;
  685. X        nextch
  686. X      until chartp[ch] in [special,illegal,chstrquo,chcolon,
  687. X                chperiod,chlt,chgt,chlparen,chspace];
  688. X      if k >= kk then kk := k
  689. X      else
  690. X        repeat id[kk] := ' '; kk := kk - 1
  691. X        until kk = k;
  692. X      for i := frw[k] to frw[k+1] - 1 do
  693. X        if rw[i] = id then
  694. X          begin sy := rsy[i]; op := rop[i]; goto 2 end;
  695. X        sy := ident; op := noop;
  696. X  2:    end;
  697. X      number:
  698. X    begin op := noop; i := 0;
  699. X      repeat i := i+1; if i<= digmax then digit[i] := ch; nextch
  700. X      until chartp[ch] <> number;
  701. X      if ((ch = '.') and (input^ <> '.')) or (ch = 'e') then
  702. X        begin
  703. X          k := i;
  704. X          if ch = '.' then
  705. X            begin k := k+1; if k <= digmax then digit[k] := ch;
  706. X              nextch; (*if ch = '.' then begin ch := ':'; goto 3 end;*)
  707. X              if chartp[ch] <> number then error(201)
  708. X              else
  709. X            repeat k := k + 1;
  710. X              if k <= digmax then digit[k] := ch; nextch
  711. X            until chartp[ch] <>  number
  712. X            end;
  713. X          if ch = 'e' then
  714. X            begin k := k+1; if k <= digmax then digit[k] := ch;
  715. X              nextch;
  716. X              if (ch = '+') or (ch ='-') then
  717. X            begin k := k+1; if k <= digmax then digit[k] := ch;
  718. X              nextch
  719. X            end;
  720. X              if chartp[ch] <> number then error(201)
  721. X              else
  722. X            repeat k := k+1;
  723. X              if k <= digmax then digit[k] := ch; nextch
  724. X            until chartp[ch] <> number
  725. X             end;
  726. X           new(lvp,reel); sy:= realconst; lvp^.cclass := reel;
  727. X           with lvp^ do
  728. X             begin for i := 1 to strglgth do rval[i] := ' ';
  729. X               if k <= digmax then
  730. X             for i := 2 to k + 1 do rval[i] := digit[i-1]
  731. X               else begin error(203); rval[2] := '0';
  732. X                  rval[3] := '.'; rval[4] := '0'
  733. X                end
  734. X             end;
  735. X           val.valp := lvp
  736. X        end
  737. X      else
  738. X  3:    begin
  739. X          if i > digmax then begin error(203); val.ival := 0 end
  740. X          else
  741. X        with val do
  742. X          begin ival := 0;
  743. X            for k := 1 to i do
  744. X              begin
  745. X            if ival <= mxint10 then
  746. X              ival := ival*10+ordint[digit[k]]
  747. X            else begin error(203); ival := 0 end
  748. X              end;
  749. X            sy := intconst
  750. X          end
  751. X        end
  752. X    end;
  753. X      chstrquo:
  754. X    begin lgth := 0; sy := stringconst;  op := noop;
  755. X      repeat
  756. X        repeat nextch; lgth := lgth + 1;
  757. X           if lgth <= strglgth then string[lgth] := ch
  758. X        until (eol) or (ch = '''');
  759. X        if eol then error(202) else nextch
  760. X      until ch <> '''';
  761. X      lgth := lgth - 1;   (*now lgth = nr of chars in string*)
  762. X      if lgth = 0 then error(205) else
  763. X      if lgth = 1 then val.ival := ord(string[1])
  764. X      else
  765. X        begin new(lvp,strg); lvp^.cclass:=strg;
  766. X          if lgth > strglgth then
  767. X        begin error(399); lgth := strglgth end;
  768. X          with lvp^ do
  769. X        begin slgth := lgth;
  770. X          for i := 1 to lgth do sval[i] := string[i]
  771. X        end;
  772. X          val.valp := lvp
  773. X        end
  774. X    end;
  775. X      chcolon:
  776. X    begin op := noop; nextch;
  777. X      if ch = '=' then
  778. X        begin sy := becomes; nextch end
  779. X      else sy := colon
  780. X    end;
  781. X      chperiod:
  782. X    begin op := noop; nextch;
  783. X      if ch = '.' then
  784. X        begin sy := colon; nextch end
  785. X      else sy := period
  786. X    end;
  787. X      chlt:
  788. X    begin nextch; sy := relop;
  789. X      if ch = '=' then
  790. X        begin op := leop; nextch end
  791. X      else
  792. X        if ch = '>' then
  793. X          begin op := neop; nextch end
  794. X        else op := ltop
  795. X    end;
  796. X      chgt:
  797. X    begin nextch; sy := relop;
  798. X      if ch = '=' then
  799. X        begin op := geop; nextch end
  800. X      else op := gtop
  801. X    end;
  802. X      chlparen:
  803. X       begin nextch;
  804. X     if ch = '*' then
  805. X       begin nextch;
  806. X         if ch = '$' then options;
  807. X         repeat
  808. X           while (ch <> '*') and not eof(input) do nextch;
  809. X           nextch
  810. X         until (ch = ')') or eof(input);
  811. X         nextch; goto 1
  812. X       end;
  813. X     sy := lparent; op := noop
  814. X       end;
  815. X      special:
  816. X    begin sy := ssy[ch]; op := sop[ch];
  817. X      nextch
  818. X    end;
  819. X      chspace: sy := othersy
  820. X    end (*case*)
  821. X  end (*insymbol*) ;
  822. X
  823. X  procedure enterid(fcp: ctp);
  824. X    (*enter id pointed at by fcp into the name-table,
  825. X     which on each declaration level is organised as
  826. X     an unbalanced binary tree*)
  827. X    var nam: alpha; lcp, lcp1: ctp; lleft: boolean;
  828. X  begin nam := fcp^.name;
  829. X    lcp := display[top].fname;
  830. X    if lcp = nil then
  831. X      display[top].fname := fcp
  832. X    else
  833. X      begin
  834. X    repeat lcp1 := lcp;
  835. X      if lcp^.name = nam then   (*name conflict, follow right link*)
  836. X        begin error(101); lcp := lcp^.rlink; lleft := false end
  837. X      else
  838. X        if lcp^.name < nam then
  839. X          begin lcp := lcp^.rlink; lleft := false end
  840. X        else begin lcp := lcp^.llink; lleft := true end
  841. X    until lcp = nil;
  842. X    if lleft then lcp1^.llink := fcp else lcp1^.rlink := fcp
  843. X      end;
  844. X    fcp^.llink := nil; fcp^.rlink := nil
  845. X  end (*enterid*) ;
  846. X
  847. X  procedure searchsection(fcp: ctp; var fcp1: ctp);
  848. X    (*to find record fields and forward declared procedure id's
  849. X     --> procedure proceduredeclaration
  850. X     --> procedure selector*)
  851. X     label 1;
  852. X  begin
  853. X    while fcp <> nil do
  854. X      if fcp^.name = id then goto 1
  855. X      else if fcp^.name < id then fcp := fcp^.rlink
  856. X    else fcp := fcp^.llink;
  857. 1:  fcp1 := fcp
  858. X  end (*searchsection*) ;
  859. X
  860. X  procedure searchid(fidcls: setofids; var fcp: ctp);
  861. X    label 1;
  862. X    var lcp: ctp;
  863. X  begin
  864. X    for disx := top downto 0 do
  865. X      begin lcp := display[disx].fname;
  866. X    while lcp <> nil do
  867. X      if lcp^.name = id then
  868. X        if lcp^.klass in fidcls then goto 1
  869. X        else
  870. X          begin if prterr then error(103);
  871. X        lcp := lcp^.rlink
  872. X          end
  873. X      else
  874. X        if lcp^.name < id then
  875. X          lcp := lcp^.rlink
  876. X        else lcp := lcp^.llink
  877. X      end;
  878. X    (*search not successful; suppress error message in case
  879. X     of forward referenced type id in pointer type definition
  880. X     --> procedure simpletype*)
  881. X    if prterr then
  882. X      begin error(104);
  883. X    (*to avoid returning nil, reference an entry
  884. X     for an undeclared id of appropriate class
  885. X     --> procedure enterundecl*)
  886. X    if types in fidcls then lcp := utypptr
  887. X    else
  888. X      if vars in fidcls then lcp := uvarptr
  889. X      else
  890. X        if field in fidcls then lcp := ufldptr
  891. X        else
  892. X          if konst in fidcls then lcp := ucstptr
  893. X          else
  894. X        if proc in fidcls then lcp := uprcptr
  895. X        else lcp := ufctptr;
  896. X      end;
  897. 1:  fcp := lcp
  898. X  end (*searchid*) ;
  899. X
  900. X  procedure getbounds(fsp: stp; var fmin,fmax: integer);
  901. X    (*get internal bounds of subrange or scalar type*)
  902. X    (*assume fsp<>intptr and fsp<>realptr*)
  903. X  begin
  904. X    fmin := 0; fmax := 0;
  905. X    if fsp <> nil then
  906. X    with fsp^ do
  907. X      if form = subrange then
  908. X    begin fmin := min.ival; fmax := max.ival end
  909. X      else
  910. X      if fsp = charptr then
  911. X        begin fmin := ordminchar; fmax := ordmaxchar
  912. X        end
  913. X      else
  914. X        if fconst <> nil then
  915. X          fmax := fconst^.values.ival
  916. X  end (*getbounds*) ;
  917. X
  918. X  function alignquot(fsp: stp): integer;
  919. X  begin
  920. X    alignquot := 1;
  921. X    if fsp <> nil then
  922. X      with fsp^ do
  923. X    case form of
  924. X      scalar:   if fsp=intptr then alignquot := intal
  925. X            else if fsp=boolptr then alignquot := boolal
  926. X            else if scalkind=declared then alignquot := intal
  927. X            else if fsp=charptr then alignquot := charal
  928. X            else if fsp=realptr then alignquot := realal
  929. X            else (*parmptr*) alignquot := parmal;
  930. X      subrange: alignquot := alignquot(rangetype);
  931. X      pointer:  alignquot := adral;
  932. X      power:    alignquot := setal;
  933. X      files:    alignquot := fileal;
  934. X      arrays:   alignquot := alignquot(aeltype);
  935. X      records:  alignquot := recal;
  936. X      variant,tagfld: error(501)
  937. X    end
  938. X  end (*alignquot*);
  939. X
  940. X  procedure align(fsp: stp; var flc: addrrange);
  941. X    var k,l: integer;
  942. X  begin
  943. X    k := alignquot(fsp);
  944. X    l := flc-1;
  945. X    flc := l + k  -  (k+l) mod k
  946. X  end (*align*);
  947. X
  948. X  procedure printtables(fb: boolean);
  949. X    (*print data structure and name table*)
  950. X    var i, lim: disprange;
  951. X
  952. X    procedure marker;
  953. X      (*mark data structure entries to avoid multiple printout*)
  954. X      var i: integer;
  955. X
  956. X      procedure markctp(fp: ctp); forward;
  957. X
  958. X      procedure markstp(fp: stp);
  959. X    (*mark data structures, prevent cycles*)
  960. X      begin
  961. X    if fp <> nil then
  962. X      with fp^ do
  963. X        begin marked := true;
  964. X          case form of
  965. X          scalar:   ;
  966. X          subrange: markstp(rangetype);
  967. X          pointer:  (*don't mark eltype: cycle possible; will be marked
  968. X            anyway, if fp = true*) ;
  969. X          power:    markstp(elset) ;
  970. X          arrays:   begin markstp(aeltype); markstp(inxtype) end;
  971. X          records:  begin markctp(fstfld); markstp(recvar) end;
  972. X          files:    markstp(filtype);
  973. X          tagfld:   markstp(fstvar);
  974. X          variant:  begin markstp(nxtvar); markstp(subvar) end
  975. X          end (*case*)
  976. X        end (*with*)
  977. X      end (*markstp*);
  978. X
  979. X      procedure markctp;
  980. X      begin
  981. X    if fp <> nil then
  982. X      with fp^ do
  983. X        begin markctp(llink); markctp(rlink);
  984. X          markstp(idtype)
  985. X        end
  986. X      end (*markctp*);
  987. X
  988. X    begin (*marker*)
  989. X      for i := top downto lim do
  990. X    markctp(display[i].fname)
  991. X    end (*marker*);
  992. X
  993. X    procedure followctp(fp: ctp); forward;
  994. X
  995. X    procedure followstp(fp: stp);
  996. X    begin
  997. X      if fp <> nil then
  998. X    with fp^ do
  999. X      if marked then
  1000. X        begin marked := false; write(output,' ':4,ord(fp):6,size:10);
  1001. X          case form of
  1002. X          scalar:   begin write(output,'scalar':10);
  1003. X              if scalkind = standard then
  1004. X                write(output,'standard':10)
  1005. X              else write(output,'declared':10,' ':4,ord(fconst):6);
  1006. X              writeln(output)
  1007. X            end;
  1008. X          subrange: begin
  1009. X              write(output,'subrange':10,' ':4,ord(rangetype):6);
  1010. X              if rangetype <> realptr then
  1011. X                write(output,min.ival,max.ival)
  1012. X              else
  1013. X                if (min.valp <> nil) and (max.valp <> nil) then
  1014. X                  write(output,' ',min.valp^.rval:9,
  1015. X                    ' ',max.valp^.rval:9);
  1016. X              writeln(output); followstp(rangetype);
  1017. X            end;
  1018. X          pointer:  writeln(output,'pointer':10,' ':4,ord(eltype):6);
  1019. X          power:    begin writeln(output,'set':10,' ':4,ord(elset):6);
  1020. X              followstp(elset)
  1021. X            end;
  1022. X          arrays:   begin
  1023. X              writeln(output,'array':10,' ':4,ord(aeltype):6,' ':4,
  1024. X                ord(inxtype):6);
  1025. X              followstp(aeltype); followstp(inxtype)
  1026. X            end;
  1027. X          records:  begin
  1028. X              writeln(output,'record':10,' ':4,ord(fstfld):6,' ':4,
  1029. X                ord(recvar):6); followctp(fstfld);
  1030. X              followstp(recvar)
  1031. X            end;
  1032. X          files:    begin write(output,'file':10,' ':4,ord(filtype):6);
  1033. X              followstp(filtype)
  1034. X            end;
  1035. X          tagfld:   begin writeln(output,'tagfld':10,' ':4,ord(tagfieldp):6,
  1036. X                ' ':4,ord(fstvar):6);
  1037. X              followstp(fstvar)
  1038. X            end;
  1039. X          variant:  begin writeln(output,'variant':10,' ':4,ord(nxtvar):6,
  1040. X                ' ':4,ord(subvar):6,varval.ival);
  1041. X              followstp(nxtvar); followstp(subvar)
  1042. X            end
  1043. X          end (*case*)
  1044. X        end (*if marked*)
  1045. X    end (*followstp*);
  1046. X
  1047. X    procedure followctp;
  1048. X      var i: integer;
  1049. X    begin
  1050. X      if fp <> nil then
  1051. X    with fp^ do
  1052. X      begin write(output,' ':4,ord(fp):6,' ',name:9,' ':4,ord(llink):6,
  1053. X        ' ':4,ord(rlink):6,' ':4,ord(idtype):6);
  1054. X        case klass of
  1055. X          types: write(output,'type':10);
  1056. X          konst: begin write(output,'constant':10,' ':4,ord(next):6);
  1057. X               if idtype <> nil then
  1058. X             if idtype = realptr then
  1059. X               begin
  1060. X                 if values.valp <> nil then
  1061. X                   write(output,' ',values.valp^.rval:9)
  1062. X               end
  1063. X             else
  1064. X               if idtype^.form = arrays then  (*stringconst*)
  1065. X                 begin
  1066. X                   if values.valp <> nil then
  1067. X                 begin write(output,' ');
  1068. X                   with values.valp^ do
  1069. X                     for i := 1 to slgth do
  1070. X                       write(output,sval[i])
  1071. X                 end
  1072. X                 end
  1073. X               else write(output,values.ival)
  1074. X             end;
  1075. X          vars:  begin write(output,'variable':10);
  1076. X               if vkind = actual then write(output,'actual':10)
  1077. X               else write(output,'formal':10);
  1078. X               write(output,' ':4,ord(next):6,vlev,' ':4,vaddr:6 );
  1079. X             end;
  1080. X          field: write(output,'field':10,' ':4,ord(next):6,' ':4,fldaddr:6);
  1081. X          proc,
  1082. X          func:  begin
  1083. X               if klass = proc then write(output,'procedure':10)
  1084. X               else write(output,'function':10);
  1085. X               if pfdeckind = standard then
  1086. X             write(output,'standard':10, key:10)
  1087. X               else
  1088. X             begin write(output,'declared':10,' ':4,ord(next):6);
  1089. X               write(output,pflev,' ':4,pfname:6);
  1090. X               if pfkind = actual then
  1091. X                 begin write(output,'actual':10);
  1092. X                   if forwdecl then write(output,'forward':10)
  1093. X                   else write(output,'notforward':10);
  1094. X                   if extern then write(output,'extern':10)
  1095. X                   else write(output,'not extern':10);
  1096. X                 end
  1097. X               else write(output,'formal':10)
  1098. X             end
  1099. X             end
  1100. X        end (*case*);
  1101. X        writeln(output);
  1102. X        followctp(llink); followctp(rlink);
  1103. X        followstp(idtype)
  1104. X      end (*with*)
  1105. X    end (*followctp*);
  1106. X
  1107. X  begin (*printtables*)
  1108. X    writeln(output); writeln(output); writeln(output);
  1109. X    if fb then lim := 0
  1110. X    else begin lim := top; write(output,' local') end;
  1111. X    writeln(output,' tables '); writeln(output);
  1112. X    marker;
  1113. X    for i := top downto lim do
  1114. X      followctp(display[i].fname);
  1115. X    writeln(output);
  1116. X    if not eol then write(output,' ':chcnt+16)
  1117. X  end (*printtables*);
  1118. X
  1119. X  procedure genlabel(var nxtlab: integer);
  1120. X  begin intlabel := intlabel + 1;
  1121. X    nxtlab := intlabel
  1122. X  end (*genlabel*);
  1123. X
  1124. X  procedure block(fsys: setofsys; fsy: symbol; fprocp: ctp);
  1125. X    var lsy: symbol; test: boolean;
  1126. X
  1127. X    procedure skip(fsys: setofsys);
  1128. X      (*skip input string until relevant symbol found*)
  1129. X    begin
  1130. X      if not eof(input) then
  1131. X    begin while not(sy in fsys) and (not eof(input)) do insymbol;
  1132. X      if not (sy in fsys) then insymbol
  1133. X    end
  1134. X    end (*skip*) ;
  1135. X
  1136. X    procedure constant(fsys: setofsys; var fsp: stp; var fvalu: valu);
  1137. X      var lsp: stp; lcp: ctp; sign: (none,pos,neg);
  1138. X      lvp: csp; i: 2..strglgth;
  1139. X    begin lsp := nil; fvalu.ival := 0;
  1140. X      if not(sy in constbegsys) then
  1141. X    begin error(50); skip(fsys+constbegsys) end;
  1142. X      if sy in constbegsys then
  1143. X    begin
  1144. X      if sy = stringconst then
  1145. X        begin
  1146. X          if lgth = 1 then lsp := charptr
  1147. X          else
  1148. X        begin
  1149. X          new(lsp,arrays);
  1150. X          with lsp^ do
  1151. X            begin aeltype := charptr; inxtype := nil;
  1152. X               size := lgth*charsize; form := arrays
  1153. X            end
  1154. X        end;
  1155. X          fvalu := val; insymbol
  1156. X        end
  1157. X      else
  1158. X        begin
  1159. X          sign := none;
  1160. X          if (sy = addop) and (op in [plus,minus]) then
  1161. X        begin if op = plus then sign := pos else sign := neg;
  1162. X          insymbol
  1163. X        end;
  1164. X          if sy = ident then
  1165. X        begin searchid([konst],lcp);
  1166. X          with lcp^ do
  1167. X            begin lsp := idtype; fvalu := values end;
  1168. X          if sign <> none then
  1169. X            if lsp = intptr then
  1170. X              begin if sign = neg then fvalu.ival := -fvalu.ival end
  1171. X            else
  1172. X              if lsp = realptr then
  1173. X            begin
  1174. X              if sign = neg then
  1175. X                begin new(lvp,reel);
  1176. X                  if fvalu.valp^.rval[1] = '-' then
  1177. X                lvp^.rval[1] := '+'
  1178. X                  else lvp^.rval[1] := '-';
  1179. X                  for i := 2 to strglgth do
  1180. X                lvp^.rval[i] := fvalu.valp^.rval[i];
  1181. X                  fvalu.valp := lvp;
  1182. X                end
  1183. X              end
  1184. X            else error(105);
  1185. X          insymbol;
  1186. X        end
  1187. X          else
  1188. X        if sy = intconst then
  1189. X          begin if sign = neg then val.ival := -val.ival;
  1190. X            lsp := intptr; fvalu := val; insymbol
  1191. X          end
  1192. X        else
  1193. X          if sy = realconst then
  1194. X            begin if sign = neg then val.valp^.rval[1] := '-';
  1195. X              lsp := realptr; fvalu := val; insymbol
  1196. X            end
  1197. X          else
  1198. X            begin error(106); skip(fsys) end
  1199. X        end;
  1200. X      if not (sy in fsys) then
  1201. X        begin error(6); skip(fsys) end
  1202. X      end;
  1203. X      fsp := lsp
  1204. X    end (*constant*) ;
  1205. X
  1206. X    function equalbounds(fsp1,fsp2: stp): boolean;
  1207. X      var lmin1,lmin2,lmax1,lmax2: integer;
  1208. X    begin
  1209. X      if (fsp1=nil) or (fsp2=nil) then equalbounds := true
  1210. X      else
  1211. X    begin
  1212. X      getbounds(fsp1,lmin1,lmax1);
  1213. X      getbounds(fsp2,lmin2,lmax2);
  1214. X      equalbounds := (lmin1=lmin2) and (lmax1=lmax2)
  1215. X    end
  1216. X    end (*equalbounds*) ;
  1217. X
  1218. X    function comptypes(fsp1,fsp2: stp) : boolean;
  1219. X      (*decide whether structures pointed at by fsp1 and fsp2 are compatible*)
  1220. X      var nxt1,nxt2: ctp; comp: boolean;
  1221. X    ltestp1,ltestp2 : testp;
  1222. X    begin
  1223. X      if fsp1 = fsp2 then comptypes := true
  1224. X      else
  1225. X    if (fsp1 <> nil) and (fsp2 <> nil) then
  1226. X      if fsp1^.form = fsp2^.form then
  1227. X        case fsp1^.form of
  1228. X          scalar:
  1229. X        comptypes := false;
  1230. X        (* identical scalars declared on different levels are
  1231. X         not recognized to be compatible*)
  1232. X          subrange:
  1233. X        comptypes := comptypes(fsp1^.rangetype,fsp2^.rangetype);
  1234. X          pointer:
  1235. X          begin
  1236. X            comp := false; ltestp1 := globtestp;
  1237. X            ltestp2 := globtestp;
  1238. X            while ltestp1 <> nil do
  1239. X              with ltestp1^ do
  1240. X            begin
  1241. X              if (elt1 = fsp1^.eltype) and
  1242. X                 (elt2 = fsp2^.eltype) then comp := true;
  1243. X              ltestp1 := lasttestp
  1244. X            end;
  1245. X            if not comp then
  1246. X              begin new(ltestp1);
  1247. X            with ltestp1^ do
  1248. X              begin elt1 := fsp1^.eltype;
  1249. X                elt2 := fsp2^.eltype;
  1250. X                lasttestp := globtestp
  1251. X              end;
  1252. X            globtestp := ltestp1;
  1253. X            comp := comptypes(fsp1^.eltype,fsp2^.eltype)
  1254. X              end;
  1255. X            comptypes := comp; globtestp := ltestp2
  1256. X          end;
  1257. X          power:
  1258. X        comptypes := comptypes(fsp1^.elset,fsp2^.elset);
  1259. X          arrays:
  1260. X        begin
  1261. X          comp := comptypes(fsp1^.aeltype,fsp2^.aeltype)
  1262. X              and comptypes(fsp1^.inxtype,fsp2^.inxtype);
  1263. X          comptypes := comp and (fsp1^.size = fsp2^.size) and
  1264. X              equalbounds(fsp1^.inxtype,fsp2^.inxtype)
  1265. X        end;
  1266. X          records:
  1267. X        begin nxt1 := fsp1^.fstfld; nxt2 := fsp2^.fstfld; comp:=true;
  1268. X          while (nxt1 <> nil) and (nxt2 <> nil) do
  1269. X            begin comp:=comp and comptypes(nxt1^.idtype,nxt2^.idtype);
  1270. X              nxt1 := nxt1^.next; nxt2 := nxt2^.next
  1271. X            end;
  1272. X          comptypes := comp and (nxt1 = nil) and (nxt2 = nil)
  1273. X                  and(fsp1^.recvar = nil)and(fsp2^.recvar = nil)
  1274. X        end;
  1275. X        (*identical records are recognized to be compatible
  1276. X         iff no variants occur*)
  1277. X          files:
  1278. X        comptypes := comptypes(fsp1^.filtype,fsp2^.filtype)
  1279. X        end (*case*)
  1280. X      else (*fsp1^.form <> fsp2^.form*)
  1281. X        if fsp1^.form = subrange then
  1282. X          comptypes := comptypes(fsp1^.rangetype,fsp2)
  1283. X        else
  1284. X          if fsp2^.form = subrange then
  1285. X        comptypes := comptypes(fsp1,fsp2^.rangetype)
  1286. X          else comptypes := false
  1287. X    else comptypes := true
  1288. X    end (*comptypes*) ;
  1289. X
  1290. X    function string(fsp: stp) : boolean;
  1291. X    begin string := false;
  1292. X      if fsp <> nil then
  1293. X    if fsp^.form = arrays then
  1294. X      if comptypes(fsp^.aeltype,charptr) then string := true
  1295. X    end (*string*) ;
  1296. X
  1297. X    procedure typ(fsys: setofsys; var fsp: stp; var fsize: addrrange);
  1298. X      var lsp,lsp1,lsp2: stp; oldtop: disprange; lcp: ctp;
  1299. X      lsize,displ: addrrange; lmin,lmax: integer;
  1300. X
  1301. X      procedure simpletype(fsys:setofsys; var fsp:stp; var fsize:addrrange);
  1302. X    var lsp,lsp1: stp; lcp,lcp1: ctp; ttop: disprange;
  1303. X        lcnt: integer; lvalu: valu;
  1304. X      begin fsize := 1;
  1305. X    if not (sy in simptypebegsys) then
  1306. X      begin error(1); skip(fsys + simptypebegsys) end;
  1307. X    if sy in simptypebegsys then
  1308. X      begin
  1309. X        if sy = lparent then
  1310. X          begin ttop := top;   (*decl. consts local to innermost block*)
  1311. X        while display[top].occur <> blck do top := top - 1;
  1312. X        new(lsp,scalar,declared);
  1313. X        with lsp^ do
  1314. X          begin size := intsize; form := scalar;
  1315. X            scalkind := declared
  1316. X          end;
  1317. X        lcp1 := nil; lcnt := 0;
  1318. X        repeat insymbol;
  1319. X          if sy = ident then
  1320. X            begin new(lcp,konst);
  1321. X              with lcp^ do
  1322. X            begin name := id; idtype := lsp; next := lcp1;
  1323. X              values.ival := lcnt; klass := konst
  1324. X            end;
  1325. X              enterid(lcp);
  1326. X              lcnt := lcnt + 1;
  1327. X              lcp1 := lcp; insymbol
  1328. X            end
  1329. X          else error(2);
  1330. X          if not (sy in fsys + [comma,rparent]) then
  1331. X            begin error(6); skip(fsys + [comma,rparent]) end
  1332. X        until sy <> comma;
  1333. X        lsp^.fconst := lcp1; top := ttop;
  1334. X        if sy = rparent then insymbol else error(4)
  1335. X          end
  1336. X        else
  1337. X          begin
  1338. X        if sy = ident then
  1339. X          begin searchid([types,konst],lcp);
  1340. X            insymbol;
  1341. X            if lcp^.klass = konst then
  1342. X              begin new(lsp,subrange);
  1343. X            with lsp^, lcp^ do
  1344. X              begin rangetype := idtype; form := subrange;
  1345. X                if string(rangetype) then
  1346. X                  begin error(148); rangetype := nil end;
  1347. X                min := values; size := intsize
  1348. X              end;
  1349. X            if sy = colon then insymbol else error(5);
  1350. X            constant(fsys,lsp1,lvalu);
  1351. X            lsp^.max := lvalu;
  1352. X            if lsp^.rangetype <> lsp1 then error(107)
  1353. X              end
  1354. X            else
  1355. X              begin lsp := lcp^.idtype;
  1356. X            if lsp <> nil then fsize := lsp^.size
  1357. X              end
  1358. X          end (*sy = ident*)
  1359. X        else
  1360. X          begin new(lsp,subrange); lsp^.form := subrange;
  1361. X            constant(fsys + [colon],lsp1,lvalu);
  1362. X            if string(lsp1) then
  1363. X              begin error(148); lsp1 := nil end;
  1364. X            with lsp^ do
  1365. X              begin rangetype:=lsp1; min:=lvalu; size:=intsize end;
  1366. X            if sy = colon then insymbol else error(5);
  1367. X            constant(fsys,lsp1,lvalu);
  1368. X            lsp^.max := lvalu;
  1369. X            if lsp^.rangetype <> lsp1 then error(107)
  1370. X          end;
  1371. X        if lsp <> nil then
  1372. X          with lsp^ do
  1373. X            if form = subrange then
  1374. X              if rangetype <> nil then
  1375. X            if rangetype = realptr then error(399)
  1376. X            else
  1377. X              if min.ival > max.ival then error(102)
  1378. X          end;
  1379. X        fsp := lsp;
  1380. X        if not (sy in fsys) then
  1381. X          begin error(6); skip(fsys) end
  1382. X      end
  1383. X        else fsp := nil
  1384. X      end (*simpletype*) ;
  1385. X
  1386. X      procedure fieldlist(fsys: setofsys; var frecvar: stp);
  1387. X    var lcp,lcp1,nxt,nxt1: ctp; lsp,lsp1,lsp2,lsp3,lsp4: stp;
  1388. X        minsize,maxsize,lsize: addrrange; lvalu: valu;
  1389. X      begin nxt1 := nil; lsp := nil;
  1390. X    if not (sy in (fsys+[ident,casesy])) then
  1391. X      begin error(19); skip(fsys + [ident,casesy]) end;
  1392. X    while sy = ident do
  1393. X      begin nxt := nxt1;
  1394. X        repeat
  1395. X          if sy = ident then
  1396. X        begin new(lcp,field);
  1397. X          with lcp^ do
  1398. X            begin name := id; idtype := nil; next := nxt;
  1399. X              klass := field
  1400. X            end;
  1401. X          nxt := lcp;
  1402. X          enterid(lcp);
  1403. X          insymbol
  1404. X        end
  1405. X          else error(2);
  1406. X          if not (sy in [comma,colon]) then
  1407. X        begin error(6); skip(fsys + [comma,colon,semicolon,casesy])
  1408. X        end;
  1409. X          test := sy <> comma;
  1410. X          if not test  then insymbol
  1411. X        until test;
  1412. X        if sy = colon then insymbol else error(5);
  1413. X        typ(fsys + [casesy,semicolon],lsp,lsize);
  1414. X        while nxt <> nxt1 do
  1415. X          with nxt^ do
  1416. X        begin align(lsp,displ);
  1417. X          idtype := lsp; fldaddr := displ;
  1418. X          nxt := next; displ := displ + lsize
  1419. X        end;
  1420. X        nxt1 := lcp;
  1421. X        while sy = semicolon do
  1422. X          begin insymbol;
  1423. X        if not (sy in fsys + [ident,casesy,semicolon]) then
  1424. X          begin error(19); skip(fsys + [ident,casesy]) end
  1425. X          end
  1426. X      end (*while*);
  1427. X    nxt := nil;
  1428. X    while nxt1 <> nil do
  1429. X      with nxt1^ do
  1430. X        begin lcp := next; next := nxt; nxt := nxt1; nxt1 := lcp end;
  1431. X    if sy = casesy then
  1432. X      begin new(lsp,tagfld);
  1433. X        with lsp^ do
  1434. X          begin tagfieldp := nil; fstvar := nil; form:=tagfld end;
  1435. X        frecvar := lsp;
  1436. X        insymbol;
  1437. X        if sy = ident then
  1438. X          begin new(lcp,field);
  1439. X        with lcp^ do
  1440. X          begin name := id; idtype := nil; klass:=field;
  1441. X            next := nil; fldaddr := displ
  1442. X          end;
  1443. X        enterid(lcp);
  1444. X        insymbol;
  1445. X        if sy = colon then insymbol else error(5);
  1446. X        if sy = ident then
  1447. X          begin searchid([types],lcp1);
  1448. X            lsp1 := lcp1^.idtype;
  1449. X            if lsp1 <> nil then
  1450. X              begin align(lsp1,displ);
  1451. X            lcp^.fldaddr := displ;
  1452. X            displ := displ+lsp1^.size;
  1453. X            if (lsp1^.form <= subrange) or string(lsp1) then
  1454. X              begin if comptypes(realptr,lsp1) then error(109)
  1455. X                else if string(lsp1) then error(399);
  1456. X                lcp^.idtype := lsp1; lsp^.tagfieldp := lcp;
  1457. X              end
  1458. X            else error(110);
  1459. X              end;
  1460. X            insymbol;
  1461. X          end
  1462. X        else begin error(2); skip(fsys + [ofsy,lparent]) end
  1463. X          end
  1464. X        else begin error(2); skip(fsys + [ofsy,lparent]) end;
  1465. X        lsp^.size := displ;
  1466. X        if sy = ofsy then insymbol else error(8);
  1467. X        lsp1 := nil; minsize := displ; maxsize := displ;
  1468. X        repeat lsp2 := nil;
  1469. X          if not (sy in fsys + [semicolon]) then
  1470. X          begin
  1471. X        repeat constant(fsys + [comma,colon,lparent],lsp3,lvalu);
  1472. X          if lsp^.tagfieldp <> nil then
  1473. X           if not comptypes(lsp^.tagfieldp^.idtype,lsp3)then error(111);
  1474. X          new(lsp3,variant);
  1475. X          with lsp3^ do
  1476. X            begin nxtvar := lsp1; subvar := lsp2; varval := lvalu;
  1477. X              form := variant
  1478. X            end;
  1479. X          lsp4 := lsp1;
  1480. X          while lsp4 <> nil do
  1481. X            with lsp4^ do
  1482. X              begin
  1483. X            if varval.ival = lvalu.ival then error(178);
  1484. X            lsp4 := nxtvar
  1485. X              end;
  1486. X          lsp1 := lsp3; lsp2 := lsp3;
  1487. X          test := sy <> comma;
  1488. X          if not test then insymbol
  1489. X        until test;
  1490. X        if sy = colon then insymbol else error(5);
  1491. X        if sy = lparent then insymbol else error(9);
  1492. X        fieldlist(fsys + [rparent,semicolon],lsp2);
  1493. X        if displ > maxsize then maxsize := displ;
  1494. X        while lsp3 <> nil do
  1495. X          begin lsp4 := lsp3^.subvar; lsp3^.subvar := lsp2;
  1496. X            lsp3^.size := displ;
  1497. X            lsp3 := lsp4
  1498. X          end;
  1499. X        if sy = rparent then
  1500. X          begin insymbol;
  1501. X            if not (sy in fsys + [semicolon]) then
  1502. X              begin error(6); skip(fsys + [semicolon]) end
  1503. X          end
  1504. X        else error(4);
  1505. X          end;
  1506. X          test := sy <> semicolon;
  1507. X          if not test then
  1508. X        begin displ := minsize;
  1509. X              insymbol
  1510. X        end
  1511. X        until test;
  1512. X        displ := maxsize;
  1513. X        lsp^.fstvar := lsp1;
  1514. X      end
  1515. X    else frecvar := nil
  1516. X      end (*fieldlist*) ;
  1517. X
  1518. X    begin (*typ*)
  1519. X      if not (sy in typebegsys) then
  1520. X     begin error(10); skip(fsys + typebegsys) end;
  1521. X      if sy in typebegsys then
  1522. X    begin
  1523. X      if sy in simptypebegsys then simpletype(fsys,fsp,fsize)
  1524. X      else
  1525. X    (*^*)     if sy = arrow then
  1526. X          begin new(lsp,pointer); fsp := lsp;
  1527. X        with lsp^ do
  1528. X          begin eltype := nil; size := ptrsize; form:=pointer end;
  1529. X        insymbol;
  1530. X        if sy = ident then
  1531. X          begin prterr := false; (*no error if search not successful*)
  1532. X            searchid([types],lcp); prterr := true;
  1533. X            if lcp = nil then   (*forward referenced type id*)
  1534. X              begin new(lcp,types);
  1535. X            with lcp^ do
  1536. X              begin name := id; idtype := lsp;
  1537. X                next := fwptr; klass := types
  1538. X              end;
  1539. X            fwptr := lcp
  1540. X              end
  1541. X            else
  1542. X              begin
  1543. X            if lcp^.idtype <> nil then
  1544. X              if lcp^.idtype^.form = files then error(108)
  1545. X              else lsp^.eltype := lcp^.idtype
  1546. X              end;
  1547. X            insymbol;
  1548. X          end
  1549. X        else error(2);
  1550. X          end
  1551. X        else
  1552. X          begin
  1553. X        if sy = packedsy then
  1554. X          begin insymbol;
  1555. X            if not (sy in typedels) then
  1556. X              begin
  1557. X            error(10); skip(fsys + typedels)
  1558. X              end
  1559. X          end;
  1560. X    (*array*)     if sy = arraysy then
  1561. X          begin insymbol;
  1562. X            if sy = lbrack then insymbol else error(11);
  1563. X            lsp1 := nil;
  1564. X            repeat new(lsp,arrays);
  1565. X              with lsp^ do
  1566. X            begin aeltype := lsp1; inxtype := nil; form:=arrays end;
  1567. X              lsp1 := lsp;
  1568. X              simpletype(fsys + [comma,rbrack,ofsy],lsp2,lsize);
  1569. X              lsp1^.size := lsize;
  1570. X              if lsp2 <> nil then
  1571. X            if lsp2^.form <= subrange then
  1572. X              begin
  1573. X                if lsp2 = realptr then
  1574. X                  begin error(109); lsp2 := nil end
  1575. X                else
  1576. X                  if lsp2 = intptr then
  1577. X                begin error(149); lsp2 := nil end;
  1578. X                lsp^.inxtype := lsp2
  1579. X              end
  1580. X            else begin error(113); lsp2 := nil end;
  1581. X              test := sy <> comma;
  1582. X              if not test then insymbol
  1583. X            until test;
  1584. X            if sy = rbrack then insymbol else error(12);
  1585. X            if sy = ofsy then insymbol else error(8);
  1586. X            typ(fsys,lsp,lsize);
  1587. X            repeat
  1588. X              with lsp1^ do
  1589. X            begin lsp2 := aeltype; aeltype := lsp;
  1590. X              if inxtype <> nil then
  1591. X                begin getbounds(inxtype,lmin,lmax);
  1592. X                  align(lsp,lsize);
  1593. X                  lsize := lsize*(lmax - lmin + 1);
  1594. X                  size := lsize
  1595. X                end
  1596. X            end;
  1597. X              lsp := lsp1; lsp1 := lsp2
  1598. X            until lsp1 = nil
  1599. X          end
  1600. X        else
  1601. X    (*record*)      if sy = recordsy then
  1602. X            begin insymbol;
  1603. X              oldtop := top;
  1604. X              if top < displimit then
  1605. X            begin top := top + 1;
  1606. X              with display[top] do
  1607. X                begin fname := nil;
  1608. X                  flabel := nil;
  1609. X                  occur := rec
  1610. X                end
  1611. X            end
  1612. X              else error(250);
  1613. X              displ := 0;
  1614. X              fieldlist(fsys-[semicolon]+[endsy],lsp1);
  1615. X              new(lsp,records);
  1616. X              with lsp^ do
  1617. X            begin fstfld := display[top].fname;
  1618. X              recvar := lsp1; size := displ; form := records
  1619. X            end;
  1620. X              top := oldtop;
  1621. X              if sy = endsy then insymbol else error(13)
  1622. X            end
  1623. X          else
  1624. X    (*set*)       if sy = setsy then
  1625. X              begin insymbol;
  1626. X            if sy = ofsy then insymbol else error(8);
  1627. X            simpletype(fsys,lsp1,lsize);
  1628. X            if lsp1 <> nil then
  1629. X              if lsp1^.form > subrange then
  1630. X                begin error(115); lsp1 := nil end
  1631. X              else
  1632. X                if lsp1 = realptr then
  1633. X                  begin error(114); lsp1 := nil end
  1634. X                else if lsp1 = intptr then
  1635. X                  begin error(169); lsp1 := nil end
  1636. X                else
  1637. X                  begin getbounds(lsp1,lmin,lmax);
  1638. X                if (lmin < setlow) or (lmax > sethigh)
  1639. X                  then error(169);
  1640. X                  end;
  1641. X            new(lsp,power);
  1642. X            with lsp^ do
  1643. X              begin elset:=lsp1; size:=setsize; form:=power end;
  1644. X              end
  1645. X            else
  1646. X    (*file*)        if sy = filesy then
  1647. X              begin insymbol;
  1648. X                error(399); skip(fsys); lsp := nil
  1649. X              end;
  1650. X        fsp := lsp
  1651. X          end;
  1652. X      if not (sy in fsys) then
  1653. X        begin error(6); skip(fsys) end
  1654. X    end
  1655. X      else fsp := nil;
  1656. X      if fsp = nil then fsize := 1 else fsize := fsp^.size
  1657. X    end (*typ*) ;
  1658. X
  1659. X    procedure labeldeclaration;
  1660. X      var llp: lbp; redef: boolean; lbname: integer;
  1661. X    begin
  1662. X      repeat
  1663. X    if sy = intconst then
  1664. X      with display[top] do
  1665. X        begin llp := flabel; redef := false;
  1666. X          while (llp <> nil) and not redef do
  1667. X        if llp^.labval <> val.ival then
  1668. X          llp := llp^.nextlab
  1669. X        else begin redef := true; error(166) end;
  1670. X          if not redef then
  1671. X        begin new(llp);
  1672. X          with llp^ do
  1673. X            begin labval := val.ival; genlabel(lbname);
  1674. X              defined := false; nextlab := flabel; labname := lbname
  1675. X            end;
  1676. X          flabel := llp
  1677. X        end;
  1678. X          insymbol
  1679. X        end
  1680. X    else error(15);
  1681. X    if not ( sy in fsys + [comma, semicolon] ) then
  1682. X      begin error(6); skip(fsys+[comma,semicolon]) end;
  1683. X    test := sy <> comma;
  1684. X    if not test then insymbol
  1685. X      until test;
  1686. X      if sy = semicolon then insymbol else error(14)
  1687. X    end (* labeldeclaration *) ;
  1688. X
  1689. X    procedure constdeclaration;
  1690. X      var lcp: ctp; lsp: stp; lvalu: valu;
  1691. X    begin
  1692. X      if sy <> ident then
  1693. X    begin error(2); skip(fsys + [ident]) end;
  1694. X      while sy = ident do
  1695. X    begin new(lcp,konst);
  1696. X      with lcp^ do
  1697. X        begin name := id; idtype := nil; next := nil; klass:=konst end;
  1698. X      insymbol;
  1699. X      if (sy = relop) and (op = eqop) then insymbol else error(16);
  1700. X      constant(fsys + [semicolon],lsp,lvalu);
  1701. X      enterid(lcp);
  1702. X      lcp^.idtype := lsp; lcp^.values := lvalu;
  1703. X      if sy = semicolon then
  1704. X        begin insymbol;
  1705. X          if not (sy in fsys + [ident]) then
  1706. X        begin error(6); skip(fsys + [ident]) end
  1707. X        end
  1708. X      else error(14)
  1709. X    end
  1710. X    end (*constdeclaration*) ;
  1711. X
  1712. X    procedure typedeclaration;
  1713. X      var lcp,lcp1,lcp2: ctp; lsp: stp; lsize: addrrange;
  1714. X    begin
  1715. X      if sy <> ident then
  1716. X    begin error(2); skip(fsys + [ident]) end;
  1717. X      while sy = ident do
  1718. X    begin new(lcp,types);
  1719. X      with lcp^ do
  1720. X        begin name := id; idtype := nil; klass := types end;
  1721. X      insymbol;
  1722. X      if (sy = relop) and (op = eqop) then insymbol else error(16);
  1723. X      typ(fsys + [semicolon],lsp,lsize);
  1724. X      enterid(lcp);
  1725. X      lcp^.idtype := lsp;
  1726. X      (*has any forward reference been satisfied:*)
  1727. X      lcp1 := fwptr;
  1728. X      while lcp1 <> nil do
  1729. X        begin
  1730. X          if lcp1^.name = lcp^.name then
  1731. X        begin lcp1^.idtype^.eltype := lcp^.idtype;
  1732. X          if lcp1 <> fwptr then
  1733. X            lcp2^.next := lcp1^.next
  1734. X          else fwptr := lcp1^.next;
  1735. X        end
  1736. X          else lcp2 := lcp1;
  1737. X          lcp1 := lcp1^.next
  1738. X        end;
  1739. X      if sy = semicolon then
  1740. X        begin insymbol;
  1741. X          if not (sy in fsys + [ident]) then
  1742. X        begin error(6); skip(fsys + [ident]) end
  1743. X        end
  1744. X      else error(14)
  1745. X    end;
  1746. X      if fwptr <> nil then
  1747. X    begin error(117); writeln(output);
  1748. X      repeat writeln(output,' type-id ',fwptr^.name);
  1749. X        fwptr := fwptr^.next
  1750. X      until fwptr = nil;
  1751. X      if not eol then write(output,' ': chcnt+16)
  1752. X    end
  1753. X    end (*typedeclaration*) ;
  1754. X
  1755. X    procedure vardeclaration;
  1756. X      var lcp,nxt: ctp; lsp: stp; lsize: addrrange;
  1757. X    begin nxt := nil;
  1758. X      repeat
  1759. X    repeat
  1760. X      if sy = ident then
  1761. X        begin new(lcp,vars);
  1762. X          with lcp^ do
  1763. X           begin name := id; next := nxt; klass := vars;
  1764. X          idtype := nil; vkind := actual; vlev := level
  1765. X        end;
  1766. X          enterid(lcp);
  1767. X          nxt := lcp;
  1768. X          insymbol;
  1769. X        end
  1770. X      else error(2);
  1771. X      if not (sy in fsys + [comma,colon] + typedels) then
  1772. X        begin error(6); skip(fsys+[comma,colon,semicolon]+typedels) end;
  1773. X      test := sy <> comma;
  1774. X      if not test then insymbol
  1775. X    until test;
  1776. X    if sy = colon then insymbol else error(5);
  1777. X    typ(fsys + [semicolon] + typedels,lsp,lsize);
  1778. X    while nxt <> nil do
  1779. X      with  nxt^ do
  1780. X        begin align(lsp,lc);
  1781. X          idtype := lsp; vaddr := lc;
  1782. X          lc := lc + lsize; nxt := next
  1783. X        end;
  1784. X    if sy = semicolon then
  1785. X      begin insymbol;
  1786. X        if not (sy in fsys + [ident]) then
  1787. X          begin error(6); skip(fsys + [ident]) end
  1788. X      end
  1789. X    else error(14)
  1790. X      until (sy <> ident) and not (sy in typedels);
  1791. X      if fwptr <> nil then
  1792. X    begin error(117); writeln(output);
  1793. X      repeat writeln(output,' type-id ',fwptr^.name);
  1794. X        fwptr := fwptr^.next
  1795. X      until fwptr = nil;
  1796. X      if not eol then write(output,' ': chcnt+16)
  1797. X    end
  1798. X    end (*vardeclaration*) ;
  1799. X
  1800. X    procedure procdeclaration(fsy: symbol);
  1801. X      var oldlev: 0..maxlevel; lcp,lcp1: ctp; lsp: stp;
  1802. X      forw: boolean; oldtop: disprange;
  1803. X      llc,lcm: addrrange; lbname: integer; markp: marktype;
  1804. X
  1805. X      procedure parameterlist(fsy: setofsys; var fpar: ctp);
  1806. X    var lcp,lcp1,lcp2,lcp3: ctp; lsp: stp; lkind: idkind;
  1807. X      llc,lsize: addrrange; count: integer;
  1808. X      begin lcp1 := nil;
  1809. X    if not (sy in fsy + [lparent]) then
  1810. X      begin error(7); skip(fsys + fsy + [lparent]) end;
  1811. X    if sy = lparent then
  1812. X      begin if forw then error(119);
  1813. X        insymbol;
  1814. X        if not (sy in [ident,varsy,procsy,funcsy]) then
  1815. X          begin error(7); skip(fsys + [ident,rparent]) end;
  1816. X        while sy in [ident,varsy,procsy,funcsy] do
  1817. X          begin
  1818. X        if sy = procsy then
  1819. X          begin error(399);
  1820. X            repeat insymbol;
  1821. X              if sy = ident then
  1822. X            begin new(lcp,proc,declared,formal);
  1823. X              with lcp^ do
  1824. X                begin name := id; idtype := nil; next := lcp1;
  1825. X                  pflev := level (*beware of parameter procedures*);
  1826. X                  klass:=proc;pfdeckind:=declared;pfkind:=formal
  1827. X                end;
  1828. X              enterid(lcp);
  1829. X              lcp1 := lcp;
  1830. X              align(parmptr,lc);
  1831. X              (*lc := lc + some size *)
  1832. X              insymbol
  1833. X            end
  1834. X              else error(2);
  1835. X              if not (sy in fsys + [comma,semicolon,rparent]) then
  1836. X            begin error(7);skip(fsys+[comma,semicolon,rparent])end
  1837. X            until sy <> comma
  1838. X          end
  1839. X        else
  1840. X          begin
  1841. X            if sy = funcsy then
  1842. X              begin error(399); lcp2 := nil;
  1843. X            repeat insymbol;
  1844. X              if sy = ident then
  1845. X                begin new(lcp,func,declared,formal);
  1846. X                  with lcp^ do
  1847. X                begin name := id; idtype := nil; next := lcp2;
  1848. X                  pflev := level (*beware param funcs*);
  1849. X                  klass:=func;pfdeckind:=declared;
  1850. X                  pfkind:=formal
  1851. X                end;
  1852. X                  enterid(lcp);
  1853. X                 lcp2 := lcp;
  1854. X                 align(parmptr,lc);
  1855. X                 (*lc := lc + some size*)
  1856. X                  insymbol;
  1857. X                end;
  1858. X              if not (sy in [comma,colon] + fsys) then
  1859. X                begin error(7);skip(fsys+[comma,semicolon,rparent])
  1860. SHAR_EOF
  1861. true || echo 'restore of pcom.p failed'
  1862. fi
  1863. echo 'End of  part 1'
  1864. echo 'File pcom.p is continued in part 2'
  1865. echo 2 > _shar_seq_.tmp
  1866. exit 0
  1867. exit 0 # Just in case...
  1868. -- 
  1869. Kent Landfield                   INTERNET: kent@sparky.IMD.Sterling.COM
  1870. Sterling Software, IMD           UUCP:     uunet!sparky!kent
  1871. Phone:    (402) 291-8300         FAX:      (402) 291-4362
  1872. Please send comp.sources.misc-related mail to kent@uunet.uu.net.
  1873.